<template>
    <div class="content-box webrtc-test">
        <div class="video-container">
            <div class="video-panel">
                <video ref="remoteVideo" autoplay playsinline></video>
                <div class="message-panel" v-if="state.logVisible">
                    <div v-html="state.messageLog"></div>
                </div>
            </div>
        </div>

        <div class="webrtc-header">
            <h1>WebRTC屏幕控制({{targetClientId}})</h1>
            <div class="top-btn">
                <el-button type="info" @click="state.logVisible = !state.logVisible">{{state.logVisible ? '关闭日志': '显示日志'}}</el-button>
                <el-button type="primary" @click="startClient(targetClientId)">发送 start 命令</el-button>
            </div>
        </div>

        <div class="status-panel">
            <h3>连接状态</h3>
            <div>信令: {{ state.signalingState }}</div>
            <div>ICE: {{ state.iceState }}</div>
            <div>连接: {{ state.connectionState }}</div>
            <div>视频流状态: {{ state.remoteStream ? '接收中' : '未接收' }}</div>
        </div>

        <div class="control-panel">
            <el-form label-width="120px" class="edit-form">
                <el-form-item label="屏幕共享设置：">
                    <el-select v-model="state.selectedSourceIndex" @change="changeScreen">
                        <el-option value="">选择屏幕源</el-option>
                        <el-option v-for="(source, key) in state.sources" :key="source.id" :value="key" :label="`${source.name} ${source.label}`"></el-option>
                    </el-select>
                    <el-button @click="refreshSources">刷新源</el-button>
                </el-form-item>
            </el-form>

        </div>

    </div>
</template>

<script setup>
import {onMounted, onUnmounted, reactive, ref, watch} from 'vue';

const props = defineProps({
    target: {
        type: String,
        default: ""
    }
})

const targetClientId = ref("");

const sigState = window.electronAPI.getSignalingState();
const remoteVideo = ref(null);

const state = reactive({
    logVisible: true,

    signalingState: sigState.signalingState,
    iceState: '',
    connectionState: '',
    messageLog: '',

    localStream: null,
    remoteStream: null,
    sources: [],
    selectedSourceIndex: 0,
})

// WebRTC 相关
let peerConnection = null;


const changeScreen = (v) => {
    console.log('改变视频', v, state.localStream);
    stopScreenShare();
    startBeControl(targetClientId.value);
}


// 发送信令消息
const sendSignalingMessage = (message) => {
    window.electronAPI.sendSignalingMessage(JSON.stringify(message))
};

const setVideoTrack = () => {
    // 添加本地流
    console.log('添加本地流', peerConnection, state.localStream)
    if (state.localStream && peerConnection) {
        state.localStream.getTracks().forEach(track => {
            console.log('推送本地流', state.localStream)
            peerConnection.addTrack(track, state.localStream);
        });
    }
}

const startBeControl = async (to) => {
    await startScreenShare();
    // 初始化 WebRTC 连接
    console.log('start方设置peerConnection')
    initializePeerConnection(to);
    setVideoTrack();
    sendSignalingMessage({
        type: 'ready',
        data: "",
        to: targetClientId.value,
    });

    setTimeout(function () {
        createOffer(to)
    }, 2000)
}

// 处理信令消息
const handleSignalingMessage = async (message) => {
    logMessage(`收到消息: ${message.type}`);
    if (message.from) targetClientId.value = message.from;

    switch (message.type) {
        case 'offer':
            logMessage('收到 Offer，可以创建 Answer');
            await createAnswer(message.data, message.to, message.from);
            break;

        case 'answer':
            logMessage('收到 Answer，可以设置到连接中');
            await addAnswer(message.data);
            break;

        case 'ice':
            if (peerConnection) {
                await peerConnection.addIceCandidate(new RTCIceCandidate(message.data));
            }
            break;
        case 'start':
            await startBeControl(message.from);
            break;
        case 'ready':
            console.log('ready方设置peerConnection')
            initializePeerConnection(message.from);
            break;
        case 'stop':
            stopScreenShare()
            break;
        case 'mouse':
            //npm install robotjs 使用JS直接操作键盘鼠标

            break;
        case 'keyboard':
            //npm install robotjs 使用JS直接操作键盘鼠标

            break;
    }
};


// 获取屏幕源
const refreshSources = async () => {
    try {
        if (window.electronAPI) {
            // [{id: 'screen:0:0', name: '屏幕 1', thumbnail: '…i3W53Pvx3yf+1DnZHT5z/B10xoDJ24FLgAAAAAElFTkSuQmCC', labe: '', width, height},
            // {id: 'window:329302:0', name: 'go – webrtc.vue', thumbnail: '…CIMi+90/j4OAYOhwOx/8H8neuxANIAMsAAAAASUVORK5CYII='}]
            state.sources = await window.electronAPI.getSources({
                types: ['screen'],
                thumbnailSize: {width: 320, height: 180}
            });
            console.log('所有屏幕信息', state.sources)
            logMessage(`找到 ${state.sources.length} 个屏幕源`);
        }
    } catch (error) {
        logMessage(`获取屏幕源失败: ${error.message}`);
    }
};

const startClient = (to) => {
    sendSignalingMessage({
        type: 'start',
        data: "",
        to: to,
    });
}

// 开始屏幕共享
const startScreenShare = async () => {
    try {
        // 获取屏幕流
        const stream = await navigator.mediaDevices.getUserMedia({
            audio: false,
            video: {
                mandatory: {
                    chromeMediaSource: 'desktop',
                    chromeMediaSourceId: state.sources[state.selectedSourceIndex].id,
                    minWidth: 1280,
                    // minHeight: 720,
                    maxWidth: 1920,
                    // maxHeight: 1080,
                    minFrameRate: 1,
                    maxFrameRate: 30
                }
            }
        });
        state.localStream = stream;
        return stream
        logMessage('屏幕共享已开始');
    } catch (error) {
        logMessage(`屏幕共享失败: ${error.message}`);
    }
};

const stopScreenShare = () => {
    if (state.localStream) {
        state.localStream.getTracks().forEach(track => track.stop());
        state.localStream = null;
    }
    if (peerConnection) {
        peerConnection.close();
        peerConnection = null;
    }

    logMessage('屏幕共享已停止');
};

// 初始化 Peer Connection
const initializePeerConnection = (to) => {
    const configuration = {
        // iceTransportPolicy: "relay",
        iceServers: [
            {urls: 'stun:stun.l.google.com:19302'},
            {urls: 'stun:stun1.l.google.com:19302'},
            {urls: 'stun:stun2.l.google.com:19302'},
            {urls: 'stun:stun3.l.google.com:19302'},
            {urls: 'stun:stun4.l.google.com:19302'},
            // {
            //     urls: "turn:101.37.81.144:3478", //101.37.81.144
            //     username: "user1",
            //     credential: "password123123",
            // },
            // {urls: 'stun:stun.qq.com:3478'},
        ]
    };

    peerConnection = new RTCPeerConnection(configuration);
    console.log('设置RTCPeerConnection', peerConnection)

    // 监听远程流
    peerConnection.ontrack = (event) => {
        logMessage('收到远程流');
        console.log('打印视频流', event.streams[0])
        state.remoteStream = event.streams[0];
        if (remoteVideo.value) {
            logMessage('----添加到video视频播放----');
            remoteVideo.value.srcObject = state.remoteStream;
        }
    };

    // ICE 连接状态
    peerConnection.oniceconnectionstatechange = () => {
        state.iceState = peerConnection.iceConnectionState;
        logMessage(`ICE 状态: ${peerConnection.iceConnectionState}`);
    };

    peerConnection.onconnectionstatechange = () => {
        state.connectionState = peerConnection.connectionState;
        logMessage(`连接状态: ${peerConnection.connectionState}`);
        if (['disconnected', 'closed', 'failed'].includes(peerConnection.connectionState)){
            stopScreenShare();
        }
    };

    // ICE 候选
    peerConnection.onicecandidate = (event) => {
        if (event.candidate) {
            console.log("ICE 候选:", event.candidate.candidate, "类型:", event.candidate.type); // host/srflx/relay
            sendSignalingMessage({
                type: 'ice',
                data: event.candidate,
                to: to,
            });
        }
    };
};

// 创建 Offer
const createOffer = async (to) => {
    if (!peerConnection) {
        logMessage('请先开始屏幕共享');
        return;
    }

    try {
        const offer = await peerConnection.createOffer({
            offerToReceiveAudio: true,
            offerToReceiveVideo: true
        });
        await peerConnection.setLocalDescription(offer);

        sendSignalingMessage({
            type: 'offer',
            to: to,
            data: offer,
        });

        logMessage('Offer 已创建并发送');
    } catch (error) {
        logMessage(`创建 Offer 失败: ${error.message}`);
    }
};

// 创建 Answer
const createAnswer = async (offer, from, to) => {
    if (!peerConnection || !offer) {
        logMessage('需要先收到 Offer');
        return false;
    }
    try {
        await peerConnection.setRemoteDescription(new RTCSessionDescription(offer));
        const answer = await peerConnection.createAnswer();
        await peerConnection.setLocalDescription(answer);
        sendSignalingMessage({
            type: 'answer',
            data: answer,
            from: from,
            to: to
        });
        logMessage('Answer 已创建并发送');
        return true;
    } catch (error) {
        logMessage(`创建 Answer 失败: ${error.message}`);
        return false;
    }
};

// 设置 Answer
const addAnswer = async (answer) => {
    if (!peerConnection || !answer) {
        logMessage('需要先收到 Answer');
        return false;
    }
    try {
        await peerConnection.setRemoteDescription(new RTCSessionDescription(answer));
        logMessage('Answer 已设置');
        return true
    } catch (error) {
        logMessage(`设置 Answer 失败: ${error.message}`);
        return false;
    }
};

// 日志记录
const logMessage = (message) => {
    const timestamp = new Date().toLocaleTimeString();
    state.messageLog = `[${timestamp}] ${message}<br>` + state.messageLog;
};

defineExpose({
    startClient,
})


// 生命周期
onMounted(() => {
    targetClientId.value = props.target;

    refreshSources();
    logMessage('WebRTC 测试工具已就绪');
    window.electronAPI.onSignalingMessage((message) => {
        handleSignalingMessage(message)
    });
    window.electronAPI.onSignalingLogMessage((message) => {
        logMessage(message)
    });


    window.electronAPI.onChildWindowMessage((msg) => {
        console.log("收到子窗口消息：", msg);
        switch (msg.type){
            case 'target':
                targetClientId.value = msg.value;
                window.electronAPI.showChildWindow(`/test/control`);
                startClient(msg.value)
                break
            case 'close':
                targetClientId.value = "";
                stopScreenShare();
                break
        }
    });
});

onUnmounted(() => {
    stopScreenShare();
});
</script>

<style scoped>
.webrtc-test {
    max-width: 100%;
    margin: 0 auto;
    font-family:"Microsoft YaHei";
    padding: 0!important;
}

.webrtc-header{
    h1{
        font-size: 16px;
    }
    display: flex;
    justify-content: space-between;
    align-items: center;
    .top-btn{
        font-size: 14px;
    }
}


.video-container {
    text-align: center;
    margin-bottom:10px;
}

.video-panel {
    text-align: center;
    width:100%;
    position: relative;
    font-size: 0;
    overflow: hidden;
}

.video-panel video {
    width: 100%;
    height: auto;
    background: #000;
    border: 1px solid #ddd;
}

.status-panel{
    margin-bottom: 20px;
    border: 1px solid #ddd;
    border-radius: 8px;
    background: #f9f9f9;
    font-size: 12px;
    padding: 2px 5px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    >div{
        min-width: 20%;
    }
}

.message-panel {
    padding:5px;
    position: absolute;
    pointer-events: none;/*屏蔽点击事件*/
    top:0;
    left:0;
    text-align:left;
    width:20%;
    height:60%;
    overflow: hidden;
    background: rgba(0,0,0, 0.5);
    font-size: 12px;
    color: #8df102;
    opacity: 0.6;
    border-radius:0 6px 6px 0;
}

</style>